关于python:如何在NumPy数组中获得N个最大值的索引?

您所在的位置:网站首页 np reval 关于python:如何在NumPy数组中获得N个最大值的索引?

关于python:如何在NumPy数组中获得N个最大值的索引?

2023-04-05 05:19| 来源: 网络整理| 查看: 265

numpy提出了一种通过np.argmax获取数组最大值索引的方法。

我想要一个类似的东西,但是返回N最大值的索引。

例如,如果我有一个数组,[1, 3, 2, 4, 5]和function(array, n=3)将返回对应于元素[5, 4, 3]的索引[4, 3, 1]。

相关讨论 python+numpy的可能副本:从矩阵中获取最小/最大n值和索引的有效方法 你的问题不是很清楚。例如,对于array([5, 1, 5, 5, 2, 3, 2, 4, 1, 5]),您期望的指数是什么,而n= 3?所有的选择中,哪一个是正确的,如[0, 2, 3]、[0, 2, 9]、...?请详细说明您的具体要求。谢谢 @吃吧,我真的不在乎在这个特定的情况下应该退回哪一个。即使返回遇到的第一个似乎合乎逻辑,这对我来说也不是一个要求。 如果你不关心归还的不雅物品的顺序,argsort可能是一个可行的选择。请看下面我的答案。

新的numpy版本(1.8及更高版本)有一个称为argpartition的函数。要获得四个最大元素的索引,请执行以下操作:

12345678>>> a = np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0]) >>> a array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0]) >>> ind = np.argpartition(a, -4)[-4:] >>> ind array([1, 5, 8, 0]) >>> a[ind] array([4, 9, 6, 9])

与argsort不同,此函数在最坏情况下以线性时间运行,但返回的指数没有排序,从评估a[ind]的结果可以看出。如果您也需要,请稍后对其进行排序:

12>>> ind[np.argsort(a[ind])] array([1, 8, 5, 0])

以这种方式获得排序顺序的前k个元素需要O(n+k logk)时间。

相关讨论 实际上,必须是O(n lg k)时间。无法想象O(n+k lg k)是怎样的 @varela argpartition使用introselect算法,以线性时间o(n)运行。随后的排序只处理k元素,因此在o(k log k)中运行。 如果有人想知道np.argpartition和它的姊妹算法np.partition的工作原理是什么,在链接的问题中有一个更详细的解释:stackoverflow.com/questions/10337533/… @弗雷德福:你为什么用-4?你这样做是为了从后面开始吗?(因为K是积极的或消极的,对我也一样!它只先打印最小的数字! 运行:{import numpy as np a = [9, 4, 4, 3, 3, 9, 0, 4, 6, 0] ind = np.argpartition(a, -4)[-4:] a[ind]}现在抛出这个错误。江户十一〔16〕号 @LKT使用a=np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0]),因为与np.array不同,普通的python列表不支持按列表进行索引。 是的。佛瑞德.福的高调回答应该有这样一个小而关键的编辑。 如何使用此方法查找矩阵每行前n个值的索引? @Umangsinghal-np.argpartition采用了可选的axis论证。查找每行前n个值的索引:np.argpartition(a, -n, axis=1)[-n:]。

我能想到的最简单的方法是:

123456In [1]: import numpy as np In [2]: arr = np.array([1, 3, 2, 4, 5]) In [3]: arr.argsort()[-3:][::-1] Out[3]: array([4, 3, 1])

这涉及到一种完整的数组。我想知道numpy是否提供了一种内置的方法来进行部分排序;到目前为止,我还没有找到一种。

如果这个解决方案的速度太慢(特别是对于小的n),那么在cython中编写一些代码可能是值得的。

相关讨论 第3行是否与arr.argsort()[-1:-4:-1]相同?我在解释器中尝试过,结果是一样的,但我想知道它是否被一些例子打破了。 @Abroekhof是的,这对于任何列表或数组都应该是等效的。或者,也可以使用np.argsort(-arr)[:3],而不用反转,我发现它更易读,更切题。 [::-1]是什么意思?@ NPE @1a11a它意味着反转一个数组(从字面上看,以相反的顺序将数组的副本从无约束的最小值复制到无约束的最大值) @Fizback那么两个:与尺寸无关对吗?整个表达式用于创建反转数组?我理解正确吗? arr.argsort()[::-1][:n]更好,因为它为n=0返回空值,而不是完整数组

更简单:

1idx = (-arr).argsort()[:n]

其中n是最大值的数目。

相关讨论 这可以用于二维数组吗?如果没有,你知道怎么做吗? @andrewhundt:只需使用(-arr).argsort(axis=-1)[:,:n] 类似的是arr[arr.argsort()[-n:]]而不是否定数组,只需从最后n个元素中取一部分

用途:

12345>>> import heapq >>> import numpy >>> a = numpy.array([1, 3, 2, 4, 5]) >>> heapq.nlargest(3, range(len(a)), a.take) [4, 3, 1]

对于常规的python列表:

123>>> a = [1, 3, 2, 4, 5] >>> heapq.nlargest(3, range(len(a)), a.__getitem__) [4, 3, 1]

如果使用python 2,请使用xrange而不是range。

来源:heapq-堆队列算法

相关讨论 这里根本不需要循环:heapq.nlargest(3, xrange(len(a)), a.take)。对于python列表,我们可以使用.__getitem__,而不是.take。 对于N维阵列,一般为A:heapq.nlargest(3, range(len(A.ravel())), A.ravel().take)。(我希望这只适用于视图,另请参见(ravel vs flatten(stackoverflow.com/a/28930580/603003))。

如果您碰巧使用多维数组,那么您将需要展平并展开索引:

123456def largest_indices(ary, n):    """Returns the n largest indices from a numpy array."""     flat = ary.flatten()     indices = np.argpartition(flat, -n)[-n:]     indices = indices[np.argsort(-flat[indices])]     return np.unravel_index(indices, ary.shape)

例如:

123456789>>> xs = np.sin(np.arange(9)).reshape((3, 3)) >>> xs array([[ 0.        ,  0.84147098,  0.90929743],        [ 0.14112001, -0.7568025 , -0.95892427],        [-0.2794155 ,  0.6569866 ,  0.98935825]]) >>> largest_indices(xs, 3) (array([2, 0, 0]), array([2, 2, 1])) >>> xs[largest_indices(xs, 3)] array([ 0.98935825,  0.90929743,  0.84147098])

如果您不关心第k个最大元素的顺序,可以使用argpartition,它的性能应该比通过argsort进行完全排序要好。

1234K = 4 # We want the indices of the four largest values a = np.array([0, 8, 0, 4, 5, 8, 8, 0, 4, 2]) np.argpartition(a,-K)[-K:] array([4, 1, 5, 6])

学分转到这个问题。

我做了一些测试,在数组大小和k值增加的情况下,argpartition的性能似乎优于argsort。

对于多维数组,可以使用axis关键字沿预期轴应用分区。

12# For a 2D array indices = np.argpartition(arr, -N, axis=1)[:, -N:]

抓取物品:

12x = arr.shape[0] arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)

但请注意,这不会返回已排序的结果。在这种情况下,您可以沿预期轴使用np.argsort():

12345indices = np.argsort(arr, axis=1)[:, -N:] # Result x = arr.shape[0] arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)

下面是一个例子:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253In [42]: a = np.random.randint(0, 20, (10, 10)) In [44]: a Out[44]: array([[ 7, 11, 12,  0,  2,  3,  4, 10,  6, 10],        [16, 16,  4,  3, 18,  5, 10,  4, 14,  9],        [ 2,  9, 15, 12, 18,  3, 13, 11,  5, 10],        [14,  0,  9, 11,  1,  4,  9, 19, 18, 12],        [ 0, 10,  5, 15,  9, 18,  5,  2, 16, 19],        [14, 19,  3, 11, 13, 11, 13, 11,  1, 14],        [ 7, 15, 18,  6,  5, 13,  1,  7,  9, 19],        [11, 17, 11, 16, 14,  3, 16,  1, 12, 19],        [ 2,  4, 14,  8,  6,  9, 14,  9,  1,  5],        [ 1, 10, 15,  0,  1,  9, 18,  2,  2, 12]]) In [45]: np.argpartition(a, np.argmin(a, axis=0))[:, 1:] # 1 is because the first item is the minimum one. Out[45]: array([[4, 5, 6, 8, 0, 7, 9, 1, 2],        [2, 7, 5, 9, 6, 8, 1, 0, 4],        [5, 8, 1, 9, 7, 3, 6, 2, 4],        [4, 5, 2, 6, 3, 9, 0, 8, 7],        [7, 2, 6, 4, 1, 3, 8, 5, 9],        [2, 3, 5, 7, 6, 4, 0, 9, 1],        [4, 3, 0, 7, 8, 5, 1, 2, 9],        [5, 2, 0, 8, 4, 6, 3, 1, 9],        [0, 1, 9, 4, 3, 7, 5, 2, 6],        [0, 4, 7, 8, 5, 1, 9, 2, 6]]) In [46]: np.argpartition(a, np.argmin(a, axis=0))[:, -3:] Out[46]: array([[9, 1, 2],        [1, 0, 4],        [6, 2, 4],        [0, 8, 7],        [8, 5, 9],        [0, 9, 1],        [1, 2, 9],        [3, 1, 9],        [5, 2, 6],        [9, 2, 6]]) In [89]: a[np.repeat(np.arange(x), 3), ind.ravel()].reshape(x, 3) Out[89]: array([[10, 11, 12],        [16, 16, 18],        [13, 15, 18],        [14, 18, 19],        [16, 18, 19],        [14, 14, 19],        [15, 18, 19],        [16, 17, 19],        [ 9, 14, 14],        [12, 15, 18]])

这将比完全排序更快,具体取决于原始数组的大小和所选内容的大小:

12345678910>>> A = np.random.randint(0,10,10) >>> A array([5, 1, 5, 5, 2, 3, 2, 4, 1, 0]) >>> B = np.zeros(3, int) >>> for i in xrange(3): ...     idx = np.argmax(A) ...     B[i]=idx; A[idx]=0 #something smaller than A.min() ...     >>> B array([0, 2, 3])

当然,它涉及篡改原始数组。您可以通过复制或替换原始值来修复(如果需要)。…以您的用例便宜的为准。

相关讨论 fwiw,您的解决方案不会在所有情况下提供明确的解决方案。OP应该描述如何处理这些明确的案例。谢谢 @吃手术的问题有点模棱两可。然而,一个实现并不能真正被解释。:)OP只需参考np.argmax docs.scipy.org/doc/numpy/reference/generated/numpy.argmax.ht‌&8203;ml的定义,以确保此特定解决方案满足要求。任何满足运营商规定要求的解决方案都有可能是可接受的。 好吧,我们也可以认为argmax(.)的实现是明确的。(imho试图遵循某种短路逻辑,但不幸的是未能提供普遍可接受的行为)。谢谢

如果仅仅为了得到n个最大值而对整个数组进行排序的开销太大,那么bottleneck具有部分排序功能。

我对这个模块一无所知;我只是在google上搜索numpy partial sort.

用途:

1234567891011121314151617def max_indices(arr, k):     '''     Returns the indices of the k first largest elements of arr     (in descending order in values)     '''     assert k > [4 7]



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3